home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / application / TextViewHTMLContainerImp.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  14.6 KB  |  363 lines  |  [TEXT/CWIE]

  1. // TextViewHTMLContainerImp.java
  2. // By Ned Etcode
  3. // Copyright 1996, 1997 Netscape Communications Corp.  All rights reserved.
  4.  
  5. package netscape.application;
  6. import netscape.util.*;
  7.  
  8. /** TextViewHTMLContainer's subclass to implement Hn,BLOCKQUOTE,DL,CENTER,PRE,
  9.   * OL,UL,MENU,DIR,ADDRESS,DT,DD,B,STRONG,EM,I,VAR,CITE,TT,CODE,SAMP,KBD,A,LI.
  10.   * This class should be private and is used to parse some HTML in the textview.
  11.   *  It is public to allow getClass() to work
  12.   *  @private
  13.   */
  14. public class TextViewHTMLContainerImp extends TextViewHTMLContainer {
  15.  
  16.     /** Add a CR if necessary + another CR */
  17.     static String markersStartingWithDoubleCarriageReturn[] =
  18.         {"H1","H2","H3","H4","H5","H6","BLOCKQUOTE","DL"};
  19.     static String markersEndingWithDoubleCarriageReturn[]   =
  20.         {"H1","H2","H3","H4","H5","H6","BLOCKQUOTE","DL"};
  21.  
  22.     /** Add a CR */
  23.     static String markersStartingWithCarriageReturn[] =
  24.          { "CENTER","PRE","OL","UL","MENU","DIR","ADDRESS","P"};
  25.     static String markersEndingWithCarriageReturn[]   =
  26.         { "CENTER","PRE","ADDRESS","LI","P" };
  27.  
  28.     static String markersStartingWithCarriageReturnOptionaly[] = { "DT","DD" };
  29.  
  30.     static final String LIST_CONTEXT = "listctxt";
  31.  
  32.     private String currentListMarker(Hashtable context) {
  33.         Vector v = (Vector) context.get(LIST_CONTEXT);
  34.         Vector m;
  35.  
  36.         if( v == null )
  37.             return null;
  38.  
  39.         m = (Vector) v.lastElement();
  40.         if( m == null || m.count() != 2)
  41.             return null;
  42.  
  43.         return (String)m.elementAt(0);
  44.     }
  45.  
  46.     private int levelOfCurrentListMarker(Hashtable context) {
  47.         Vector v = (Vector) context.get(LIST_CONTEXT);
  48.         Vector m;
  49.  
  50.         if( v == null )
  51.             return 1;
  52.         return v.count();
  53.     }
  54.  
  55.     private void addListInContext(String aMarker,Hashtable context) {
  56.         Vector v = (Vector) context.get(LIST_CONTEXT);
  57.         Vector m = new Vector();
  58.         m.addElement(aMarker);
  59.         m.addElement("0");
  60.         if( v != null )
  61.             v.addElement(m);
  62.         else {
  63.             v = new Vector();
  64.             v.addElement(m);
  65.             context.put(LIST_CONTEXT,v);
  66.         }
  67.     }
  68.  
  69.     private void removeLastListFromContext(Hashtable context) {
  70.         Vector v = (Vector) context.get(LIST_CONTEXT);
  71.         Vector m;
  72.         if( v != null && (m = (Vector)v.lastElement()) != null ) {
  73.             v.removeLastElement();
  74.         }
  75.     }
  76.  
  77.     private void bumpNumberOfListItemProcessed(Hashtable context) {
  78.         Vector v = (Vector) context.get(LIST_CONTEXT);
  79.         Vector m;
  80.         if( v != null && (m = (Vector)v.lastElement()) != null ) {
  81.             String n;
  82.             n = (String) m.elementAt(1);
  83.             n = "" + (Integer.parseInt((String)m.elementAt(1)) + 1);
  84.             m.removeLastElement();
  85.             m.addElement(n);
  86.         }
  87.     }
  88.  
  89.     private int numberOfListItemProcessed(Hashtable context) {
  90.         Vector v = (Vector) context.get(LIST_CONTEXT);
  91.         Vector m;
  92.         if( v != null && (m = (Vector)v.lastElement()) != null ) {
  93.             return Integer.parseInt((String) m.elementAt(1));
  94.         }
  95.         return 0;
  96.     }
  97.  
  98.  
  99.     /**
  100.      * You can override this method to return what string should prefix the container.
  101.      * This method is usualy used to add extra characters like cariage returns. For example,
  102.      * Headers always start with a cariage return. This method for an header should return
  103.      * a cariage return.
  104.      * <b>context</b> is the context
  105.      * <b>lastchar</b> is the last character added to the textView. It is often useful to
  106.      * check if lastChar is '\n' before adding another '\n'
  107.      * The default implementation returns nothing.
  108.      */
  109.      public String prefix(Hashtable context, char lastChar) {
  110.         int i,c;
  111.  
  112.         if (marker.equals("LI")) {
  113.             String markerType = currentListMarker(context);
  114.             int level;
  115.             if( markerType == null ) /* LI without list ignore */
  116.                 return null;
  117.             else {
  118.                 FastStringBuffer lfb = new FastStringBuffer();
  119.                 level = levelOfCurrentListMarker(context);
  120.  
  121.                 for(i=0;i<level;i++)
  122.                     lfb.append("\t");
  123.                 if(markerType.equals("OL"))
  124.                     return lfb.toString()  +
  125.                         (numberOfListItemProcessed(context) + 1) + ". ";
  126.                 else
  127.                     return lfb.toString() + "\u00b7 ";
  128.             }
  129.         }
  130.         for(i=0,c=markersStartingWithDoubleCarriageReturn.length ; i < c ; i++)
  131.             if( markersStartingWithDoubleCarriageReturn[i].equals(marker)) {
  132.                 if(lastChar != '\n')
  133.                     return "\n\n";
  134.                 else
  135.                     return "\n";
  136.             }
  137.  
  138.         for(i=0,c=markersStartingWithCarriageReturn.length ; i < c ; i++)
  139.             if( markersStartingWithCarriageReturn[i].equals(marker))
  140.               return "\n";
  141.  
  142.         if( lastChar != '\n') {
  143.           for(i=0,c=markersStartingWithCarriageReturnOptionaly.length ; i < c ; i++ )
  144.             if( markersStartingWithCarriageReturnOptionaly[i].equals(marker))
  145.               return "\n";
  146.         }
  147.         return "";
  148.      }
  149.  
  150.  
  151.     /**
  152.      * You can override this method to return what string should suffix the container.
  153.      * This method is usualy used to add extra characters like cariage returns. For example,
  154.      * Headers always end with a cariage return. This method for an header should return
  155.      * a cariage return.
  156.      * <b>context</b> is the context
  157.      * <b>lastchar</b> is the last character added to the textView. It is often useful to
  158.      * check if lastChar is '\n' before adding another '\n'
  159.      * The default implementation returns nothing.
  160.      */
  161.      public String suffix(Hashtable context, char lastChar) {
  162.         int i,c;
  163.  
  164.         for(i=0,c=markersEndingWithDoubleCarriageReturn.length ; i < c ; i++)
  165.             if( markersEndingWithDoubleCarriageReturn[i].equals(marker)){
  166.                 if( lastChar != '\n' )
  167.                     return "\n\n";
  168.                 else
  169.                     return "\n";
  170.             }
  171.  
  172.         for(i=0,c=markersEndingWithCarriageReturn.length ; i < c ; i++)
  173.             if( markersEndingWithCarriageReturn[i].equals(marker)) {
  174.                     return "\n";
  175.             }
  176.  
  177.         return "";
  178.      }
  179.  
  180.  
  181.     /**
  182.      *  Setup the context for children. Override this method and add or change
  183.      *  any key if you want to add some state for children.
  184.      *  The default implementation does nothing.
  185.      */
  186.     public void setupContext(Hashtable context) {
  187.         if( marker.equals("OL") || marker.equals("UL") ||
  188.             marker.equals("DIR") || marker.equals("MENU"))
  189.             addListInContext(marker,context);
  190.         else if( marker.equals("LI") && currentListMarker(context) != null ) {
  191.             bumpNumberOfListItemProcessed(context);
  192.         }
  193.     }
  194.  
  195.  
  196.     /**
  197.      *  Cleanup the context. If you have added some state in setupContext,
  198.      *  you should override this method and remove any state added during
  199.      *  setupContext()
  200.      *  The default implementation does nothing
  201.      */
  202.     public void cleanupContext(Hashtable context) {
  203.         if( marker.equals("OL") || marker.equals("UL") ||
  204.             marker.equals("DIR") || marker.equals("MENU"))
  205.             removeLastListFromContext(context);
  206.     }
  207.  
  208.     public String string(Hashtable context) {
  209.         if( marker.equals("TITLE"))
  210.             return "";
  211.         else
  212.             return super.string(context);
  213.     }
  214.     /**
  215.      *  Compute the TextView attributes for the container contents according to the
  216.      *  context and initial attributes.
  217.      *  Return the new attributes. The default implementation
  218.      *  returns <b> initialAttributes</b>
  219.      *  It is not necessary to allocate a new hashtable.You can just
  220.      *  modify initialAttributes and return it.
  221.      *  textView is the TextView for which the HTML is parsed.
  222.      */
  223.     public Hashtable attributesForContents(Hashtable context,Hashtable initialAttributes,TextView textView) {
  224.         Hashtable newAttr;
  225.         Font defaultFont = Font.defaultFont();
  226.  
  227.         if( initialAttributes != null && initialAttributes.count() > 0) {
  228.           Enumeration enumeration;
  229.           Object key;
  230.  
  231.           newAttr = (Hashtable) TextView.hashtablePool.allocateObject();
  232.           enumeration = initialAttributes.keys();
  233.           while(enumeration.hasMoreElements() ) {
  234.             key = enumeration.nextElement();
  235.             newAttr.put(key,initialAttributes.get(key));
  236.           }
  237.         } else
  238.             newAttr = (Hashtable)TextView.hashtablePool.allocateObject();
  239.  
  240.         if( marker.equals("H1"))
  241.             newAttr.put(TextView.FONT_KEY, Font.fontNamed(defaultFont.name(),
  242.                                                           Font.BOLD, 24));
  243.         else if( marker.equals("H2"))
  244.             newAttr.put(TextView.FONT_KEY, Font.fontNamed(defaultFont.name(),
  245.                                                           Font.BOLD, 18));
  246.         else if( marker.equals("H3"))
  247.             newAttr.put(TextView.FONT_KEY, Font.fontNamed(defaultFont.name(),
  248.                                                           Font.BOLD, 16));
  249.         else if( marker.equals("H4"))
  250.             newAttr.put(TextView.FONT_KEY, Font.fontNamed(defaultFont.name(),
  251.                                                           Font.BOLD, 12));
  252.         else if( marker.equals("H5"))
  253.             newAttr.put(TextView.FONT_KEY, Font.fontNamed(defaultFont.name(),
  254.                                                           Font.BOLD,  10));
  255.         else if( marker.equals("H6"))
  256.             newAttr.put(TextView.FONT_KEY, Font.fontNamed(defaultFont.name(),
  257.                                                           Font.BOLD,  8));
  258.         else if( marker.equals("B") || marker.equals("STRONG")) {
  259.             Font f = (Font) newAttr.get(TextView.FONT_KEY);
  260.             if( f != null ) {
  261.                 if(!f.isBold())
  262.                     newAttr.put(TextView.FONT_KEY, Font.fontNamed( f.name(),
  263.                                    f.style() | Font.BOLD,f.size()));
  264.             } else {
  265.                 newAttr.put(TextView.FONT_KEY, Font.fontNamed(defaultFont.name(),Font.BOLD,
  266.                                                         defaultFont.size()));
  267.             }
  268.         } else if( marker.equals("CENTER")) {
  269.             TextParagraphFormat pf = (TextParagraphFormat)
  270.                 newAttr.get(TextView.PARAGRAPH_FORMAT_KEY);
  271.             TextParagraphFormat centerFormat;
  272.             if( pf != null )
  273.                 centerFormat = (TextParagraphFormat)pf.clone();
  274.              else
  275.                 centerFormat = (TextParagraphFormat)
  276.                     ((TextParagraphFormat)initialAttributes.get(
  277.                                         TextView.PARAGRAPH_FORMAT_KEY)).clone();
  278.             centerFormat.setJustification(Graphics.CENTERED);
  279.             newAttr.put( TextView.PARAGRAPH_FORMAT_KEY, centerFormat );
  280.         } else if( marker.equals("BLOCKQUOTE") || marker.equals("DD")) {
  281.             TextParagraphFormat pf = (TextParagraphFormat)
  282.             newAttr.get(TextView.PARAGRAPH_FORMAT_KEY);
  283.             TextParagraphFormat indentFormat;
  284.             if( pf != null )
  285.                 indentFormat = (TextParagraphFormat)pf.clone();
  286.              else
  287.                 indentFormat = (TextParagraphFormat)
  288.                     ((TextParagraphFormat)initialAttributes.get(
  289.                                 TextView.PARAGRAPH_FORMAT_KEY)).clone();
  290.             indentFormat.setLeftMargin(50);
  291.             newAttr.put( TextView.PARAGRAPH_FORMAT_KEY, indentFormat );
  292.         } else if( marker.equals("EM") || marker.equals("I") || marker.equals("ADDRESS") ||
  293.                    marker.equals("VAR") || marker.equals("CITE")) {
  294.             Font f = (Font) newAttr.get(TextView.FONT_KEY);
  295.             if( f != null ) {
  296.                 if(!f.isItalic())
  297.                     newAttr.put(TextView.FONT_KEY, Font.fontNamed( f.name(),
  298.                                 f.style() | Font.ITALIC,f.size()));
  299.             } else {
  300.                 newAttr.put(TextView.FONT_KEY, Font.fontNamed(
  301.                      defaultFont.name(),Font.ITALIC,defaultFont.size()));
  302.             }
  303.         } else if( marker.equals("PRE")) {
  304.             Font f = (Font) newAttr.get(TextView.FONT_KEY);
  305.             TextParagraphFormat defaultFormat = (TextParagraphFormat)
  306.                 ((TextParagraphFormat)initialAttributes.get(
  307.                           TextView.PARAGRAPH_FORMAT_KEY)).clone();
  308.             if( f == null )
  309.                 f = Font.defaultFont();
  310.             newAttr.put(TextView.FONT_KEY, Font.fontNamed( "Courier", f.style(), f.size()));
  311.             newAttr.put(TextView.PARAGRAPH_FORMAT_KEY, defaultFormat);
  312.         } else if(marker.equals("TT") || marker.equals("CODE") ||
  313.                   marker.equals("SAMP") || marker.equals("KBD")) {
  314.             Font f = (Font) newAttr.get(TextView.FONT_KEY);
  315.             if( f == null )
  316.                 f = Font.defaultFont();
  317.             newAttr.put(TextView.FONT_KEY, Font.fontNamed( "Courier", f.style(), f.size()));
  318.         } else if( marker.equals("A")) {
  319.           Hashtable attr;
  320.           String url;
  321.           String name;
  322.  
  323.           attr = hashtableForHTMLAttributes(attributes);
  324.  
  325.           if( attr != null ) {
  326.             if( (url = (String)attr.get("HREF")) != null) {
  327.               newAttr.put( TextView.LINK_KEY, url);
  328.             }
  329.  
  330.             if((name = (String) attr.get("NAME")) != null ) {
  331.               newAttr.put( TextView.LINK_DESTINATION_KEY, name);
  332.             }
  333.           }
  334.         } else if( marker.equals("LI")) {
  335.             TextParagraphFormat pf =(TextParagraphFormat) newAttr.get(
  336.                                       TextView.PARAGRAPH_FORMAT_KEY);
  337.             if( pf == null )
  338.                 pf = (TextParagraphFormat)
  339.                     ((TextParagraphFormat)initialAttributes.get(
  340.                                 TextView.PARAGRAPH_FORMAT_KEY)).clone();
  341.             pf.setWrapsUnderFirstCharacter(true);
  342.             newAttr.put(TextView.PARAGRAPH_FORMAT_KEY, pf);
  343.         } else if( marker.equals("P")) {
  344.             Hashtable attr = hashtableForHTMLAttributes(attributes);
  345.             String v;
  346.             if((v=(String)attr.get("ALIGN")) != null) {
  347.                 TextParagraphFormat f = (TextParagraphFormat)
  348.                     initialAttributes.get(TextView.PARAGRAPH_FORMAT_KEY);
  349.                 f = (TextParagraphFormat) f.clone();
  350.                 v = v.toUpperCase();
  351.                 if(v.equals("LEFT"))
  352.                     f.setJustification(Graphics.LEFT_JUSTIFIED);
  353.                 else if(v.equals("CENTER"))
  354.                     f.setJustification(Graphics.CENTERED);
  355.                 else if(v.equals("RIGHT"))
  356.                     f.setJustification(Graphics.RIGHT_JUSTIFIED);
  357.                 newAttr.put(TextView.PARAGRAPH_FORMAT_KEY,f);
  358.             }
  359.         }
  360.         return newAttr;
  361.     }
  362. }
  363.